<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Strict//EN">
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>Threaded and non-threaded script code</title>
<link rel="stylesheet" type="text/css" href="../style.css">
</head>

<body>

<div align="center">
<table class=allEncompassingTable >
 <tr>
  <td >
<p><a href="../index.html" TARGET="_top"><img src="images/homeImg.png"></a></p>



<h1>Threaded and non-threaded script code</h1>

<p>Any type of script can run <a href="#threaded">threaded</a> and/or <a href="#nonThreaded">non-threaded</a> script functions. </p>

<table class=subsectionTable><tr class=subsectionTd>
  <td class=subsectionTd>
<a name="nonThreaded"></a>Non-threaded code
</td></tr></table> 

<p>The entrance to a script is always originating from <a href="callbackFunctions.htm">callback functions</a> which are not running threaded, and should not be blocking. This means that every time they are called, they should perform some task and then return control. If control is not returned, then CoppeliaSim will halt. </p>
<p>Non-threaded code runs faster than threaded code, since there is no overhead in handling the thread creation, switching or resume function. It also has inherent synchronization  with the simulation loop.</p>
<br>



<table class=subsectionTable><tr class=subsectionTd>
  <td class=subsectionTd>
<a name="threaded"></a>Threaded code
</td></tr></table> 


<p>Threading in a script is achieved via <a href="https://en.wikipedia.org/wiki/Coroutine" target="_blank">coroutines</a>, that CoppeliaSim will preemptively interrupt (i.e. yield, or switch) at regular intervals, and resume at a later point. In this context, we will refer to <em>threads</em> and <em>coroutines</em> , <em>interrupt</em>, <em>yield</em> and <em>switch</em>, in an interchangeable manner.</p>

<p>Threaded code has several weaknesses compared to non-threaded code if not programmed appropriately: it is  more resource-intensive, and it can waste some processing time. Following shows a typical threaded function (i.e. <em>coroutineMain</em>), which however is not perfect since <strong>it is wasting precious computation time</strong> in the loop:<br>
</p>
<pre class=lightRedBox>
function sysCall_init()
    corout=coroutine.create(coroutineMain) -- create the coroutine
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout) -- resume the coroutine
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    for i=1,100,1 do
        print('simulation time: ',sim.getSimulationTime())
    end
end</pre>

<p>By default a threaded code section will execute for about 1-2 milliseconds before automatically interrupting or <em>switching</em> and giving control back to the caller. This default behavior can be changed with the <a href="regularApi/simSetThreadSwitchTiming.htm">sim.setThreadSwitchTiming</a> or <a href="regularApi/simSetThreadAutomaticSwitch.htm">sim.setThreadAutomaticSwitch</a>. Once the current thread was switched, it will resume next time the coroutine is resumed (which often is in next simulation step. The thread switching is automatic and is handled by CoppeliaSim (occurs after the specified time), but the <a href="regularApi/simSwitchThread.htm">sim.switchThread</a> command allows to explicitely switch when needed. Using above three commands, a perfect synchronization with the main simulation loop can be achieved. Following code shows code synchronization with the main simulation loop:<br>
</p>
<pre class=lightRedBox>
function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    local savedLockLevel=sim.setThreadAutomaticSwitch(false) -- forbid automatic switches
    for i=1,100,1 do
        print('simulation time: ',sim.getSimulationTime())
        sim.switchThread() -- resume in next simulation step
    end
    sim.setThreadAutomaticSwitch(savedLockLevel) -- restore automatic switch behaviour
end</pre>

<p>Above while loop will now execute exactly once for each main simulation step and not waste time reading and printing the simulation time over and over for same simulation step.
</p>

<p>Some operation should not be interrupted in order to execute correctly (imagine moving several objects in a loop). In that case, you can temporarily forbid thread switches with the <a href="regularApi/simSetThreadAutomaticSwitch.htm">sim.setThreadAutomaticSwitch</a> function.</p>
<p>Several <a href="apiFunctions.htm#blockingFunctions">blocking functions</a> are specifically meant to be running from within threaded code, e.g. <a href="regularApi/simMoveToConfig.htm">sim.moveToConfig</a>: those functions will handle thread switching for you, at the appropriate time, in order to operate synchronously with the simulation loop.</p>

<br>
<br>
 </tr>
</table> 
</div>  
  
  
</body>

</html>
